﻿using System;
using UnityEngine;

namespace RootMotion
{
	// Token: 0x020001D3 RID: 467
	[Serializable]
	public class BipedReferences
	{
		// Token: 0x170000C5 RID: 197
		// (get) Token: 0x0600099B RID: 2459 RVA: 0x00034048 File Offset: 0x00032448
		public virtual bool isFilled
		{
			get
			{
				if (this.root == null)
				{
					return false;
				}
				if (this.pelvis == null)
				{
					return false;
				}
				if (this.leftThigh == null || this.leftCalf == null || this.leftFoot == null)
				{
					return false;
				}
				if (this.rightThigh == null || this.rightCalf == null || this.rightFoot == null)
				{
					return false;
				}
				if (this.leftUpperArm == null || this.leftForearm == null || this.leftHand == null)
				{
					return false;
				}
				if (this.rightUpperArm == null || this.rightForearm == null || this.rightHand == null)
				{
					return false;
				}
				foreach (Transform x in this.spine)
				{
					if (x == null)
					{
						return false;
					}
				}
				foreach (Transform x2 in this.eyes)
				{
					if (x2 == null)
					{
						return false;
					}
				}
				return true;
			}
		}

		// Token: 0x170000C6 RID: 198
		// (get) Token: 0x0600099C RID: 2460 RVA: 0x000341B2 File Offset: 0x000325B2
		public bool isEmpty
		{
			get
			{
				return this.IsEmpty(true);
			}
		}

		// Token: 0x0600099D RID: 2461 RVA: 0x000341BC File Offset: 0x000325BC
		public virtual bool IsEmpty(bool includeRoot)
		{
			if (includeRoot && this.root != null)
			{
				return false;
			}
			if (this.pelvis != null || this.head != null)
			{
				return false;
			}
			if (this.leftThigh != null || this.leftCalf != null || this.leftFoot != null)
			{
				return false;
			}
			if (this.rightThigh != null || this.rightCalf != null || this.rightFoot != null)
			{
				return false;
			}
			if (this.leftUpperArm != null || this.leftForearm != null || this.leftHand != null)
			{
				return false;
			}
			if (this.rightUpperArm != null || this.rightForearm != null || this.rightHand != null)
			{
				return false;
			}
			foreach (Transform x in this.spine)
			{
				if (x != null)
				{
					return false;
				}
			}
			foreach (Transform x2 in this.eyes)
			{
				if (x2 != null)
				{
					return false;
				}
			}
			return true;
		}

		// Token: 0x0600099E RID: 2462 RVA: 0x00034340 File Offset: 0x00032740
		public virtual bool Contains(Transform t, bool ignoreRoot = false)
		{
			if (!ignoreRoot && this.root == t)
			{
				return true;
			}
			if (this.pelvis == t)
			{
				return true;
			}
			if (this.leftThigh == t)
			{
				return true;
			}
			if (this.leftCalf == t)
			{
				return true;
			}
			if (this.leftFoot == t)
			{
				return true;
			}
			if (this.rightThigh == t)
			{
				return true;
			}
			if (this.rightCalf == t)
			{
				return true;
			}
			if (this.rightFoot == t)
			{
				return true;
			}
			if (this.leftUpperArm == t)
			{
				return true;
			}
			if (this.leftForearm == t)
			{
				return true;
			}
			if (this.leftHand == t)
			{
				return true;
			}
			if (this.rightUpperArm == t)
			{
				return true;
			}
			if (this.rightForearm == t)
			{
				return true;
			}
			if (this.rightHand == t)
			{
				return true;
			}
			if (this.head == t)
			{
				return true;
			}
			foreach (Transform x in this.spine)
			{
				if (x == t)
				{
					return true;
				}
			}
			foreach (Transform x2 in this.eyes)
			{
				if (x2 == t)
				{
					return true;
				}
			}
			return false;
		}

		// Token: 0x0600099F RID: 2463 RVA: 0x000344D4 File Offset: 0x000328D4
		public static bool AutoDetectReferences(ref BipedReferences references, Transform root, BipedReferences.AutoDetectParams autoDetectParams)
		{
			if (references == null)
			{
				references = new BipedReferences();
			}
			references.root = root;
			Animator component = root.GetComponent<Animator>();
			if (component != null && component.isHuman)
			{
				BipedReferences.AssignHumanoidReferences(ref references, component, autoDetectParams);
				return true;
			}
			BipedReferences.DetectReferencesByNaming(ref references, root, autoDetectParams);
			Warning.logged = false;
			if (!references.isFilled)
			{
				Warning.Log("BipedReferences contains one or more missing Transforms.", root, true);
				return false;
			}
			string empty = string.Empty;
			if (BipedReferences.SetupError(references, ref empty))
			{
				Warning.Log(empty, references.root, true);
				return false;
			}
			if (BipedReferences.SetupWarning(references, ref empty))
			{
				Warning.Log(empty, references.root, true);
			}
			return true;
		}

		// Token: 0x060009A0 RID: 2464 RVA: 0x00034588 File Offset: 0x00032988
		public static void DetectReferencesByNaming(ref BipedReferences references, Transform root, BipedReferences.AutoDetectParams autoDetectParams)
		{
			if (references == null)
			{
				references = new BipedReferences();
			}
			Transform[] componentsInChildren = root.GetComponentsInChildren<Transform>();
			BipedReferences.DetectLimb(BipedNaming.BoneType.Arm, BipedNaming.BoneSide.Left, ref references.leftUpperArm, ref references.leftForearm, ref references.leftHand, componentsInChildren);
			BipedReferences.DetectLimb(BipedNaming.BoneType.Arm, BipedNaming.BoneSide.Right, ref references.rightUpperArm, ref references.rightForearm, ref references.rightHand, componentsInChildren);
			BipedReferences.DetectLimb(BipedNaming.BoneType.Leg, BipedNaming.BoneSide.Left, ref references.leftThigh, ref references.leftCalf, ref references.leftFoot, componentsInChildren);
			BipedReferences.DetectLimb(BipedNaming.BoneType.Leg, BipedNaming.BoneSide.Right, ref references.rightThigh, ref references.rightCalf, ref references.rightFoot, componentsInChildren);
			references.head = BipedNaming.GetBone(componentsInChildren, BipedNaming.BoneType.Head, BipedNaming.BoneSide.Center, new string[0][]);
			references.pelvis = BipedNaming.GetNamingMatch(componentsInChildren, new string[][]
			{
				BipedNaming.pelvis
			});
			if ((references.pelvis == null || !Hierarchy.IsAncestor(references.leftThigh, references.pelvis)) && references.leftThigh != null)
			{
				references.pelvis = references.leftThigh.parent;
			}
			if (references.leftUpperArm != null && references.rightUpperArm != null && references.pelvis != null && references.leftThigh != null)
			{
				Transform firstCommonAncestor = Hierarchy.GetFirstCommonAncestor(references.leftUpperArm, references.rightUpperArm);
				if (firstCommonAncestor != null)
				{
					Transform[] array = new Transform[]
					{
						firstCommonAncestor
					};
					Hierarchy.AddAncestors(array[0], references.pelvis, ref array);
					references.spine = new Transform[0];
					for (int i = array.Length - 1; i > -1; i--)
					{
						if (BipedReferences.AddBoneToSpine(array[i], ref references, autoDetectParams))
						{
							Array.Resize<Transform>(ref references.spine, references.spine.Length + 1);
							references.spine[references.spine.Length - 1] = array[i];
						}
					}
					if (references.head == null)
					{
						for (int j = 0; j < firstCommonAncestor.childCount; j++)
						{
							Transform child = firstCommonAncestor.GetChild(j);
							if (!Hierarchy.ContainsChild(child, references.leftUpperArm) && !Hierarchy.ContainsChild(child, references.rightUpperArm))
							{
								references.head = child;
								break;
							}
						}
					}
				}
			}
			Transform[] bonesOfType = BipedNaming.GetBonesOfType(BipedNaming.BoneType.Eye, componentsInChildren);
			references.eyes = new Transform[0];
			if (autoDetectParams.includeEyes)
			{
				for (int k = 0; k < bonesOfType.Length; k++)
				{
					if (BipedReferences.AddBoneToEyes(bonesOfType[k], ref references, autoDetectParams))
					{
						Array.Resize<Transform>(ref references.eyes, references.eyes.Length + 1);
						references.eyes[references.eyes.Length - 1] = bonesOfType[k];
					}
				}
			}
		}

		// Token: 0x060009A1 RID: 2465 RVA: 0x00034868 File Offset: 0x00032C68
		public static void AssignHumanoidReferences(ref BipedReferences references, Animator animator, BipedReferences.AutoDetectParams autoDetectParams)
		{
			if (references == null)
			{
				references = new BipedReferences();
			}
			if (animator == null || !animator.isHuman)
			{
				return;
			}
			references.spine = new Transform[0];
			references.eyes = new Transform[0];
			references.head = animator.GetBoneTransform(HumanBodyBones.Head);
			references.leftThigh = animator.GetBoneTransform(HumanBodyBones.LeftUpperLeg);
			references.leftCalf = animator.GetBoneTransform(HumanBodyBones.LeftLowerLeg);
			references.leftFoot = animator.GetBoneTransform(HumanBodyBones.LeftFoot);
			references.rightThigh = animator.GetBoneTransform(HumanBodyBones.RightUpperLeg);
			references.rightCalf = animator.GetBoneTransform(HumanBodyBones.RightLowerLeg);
			references.rightFoot = animator.GetBoneTransform(HumanBodyBones.RightFoot);
			references.leftUpperArm = animator.GetBoneTransform(HumanBodyBones.LeftUpperArm);
			references.leftForearm = animator.GetBoneTransform(HumanBodyBones.LeftLowerArm);
			references.leftHand = animator.GetBoneTransform(HumanBodyBones.LeftHand);
			references.rightUpperArm = animator.GetBoneTransform(HumanBodyBones.RightUpperArm);
			references.rightForearm = animator.GetBoneTransform(HumanBodyBones.RightLowerArm);
			references.rightHand = animator.GetBoneTransform(HumanBodyBones.RightHand);
			references.pelvis = animator.GetBoneTransform(HumanBodyBones.Hips);
			BipedReferences.AddBoneToHierarchy(ref references.spine, animator.GetBoneTransform(HumanBodyBones.Spine));
			BipedReferences.AddBoneToHierarchy(ref references.spine, animator.GetBoneTransform(HumanBodyBones.Chest));
			if (references.leftUpperArm != null && !BipedReferences.IsNeckBone(animator.GetBoneTransform(HumanBodyBones.Neck), references.leftUpperArm))
			{
				BipedReferences.AddBoneToHierarchy(ref references.spine, animator.GetBoneTransform(HumanBodyBones.Neck));
			}
			if (autoDetectParams.includeEyes)
			{
				BipedReferences.AddBoneToHierarchy(ref references.eyes, animator.GetBoneTransform(HumanBodyBones.LeftEye));
				BipedReferences.AddBoneToHierarchy(ref references.eyes, animator.GetBoneTransform(HumanBodyBones.RightEye));
			}
		}

		// Token: 0x060009A2 RID: 2466 RVA: 0x00034A1C File Offset: 0x00032E1C
		public static bool SetupError(BipedReferences references, ref string errorMessage)
		{
			if (!references.isFilled)
			{
				errorMessage = "BipedReferences contains one or more missing Transforms.";
				return true;
			}
			return BipedReferences.LimbError(references.leftThigh, references.leftCalf, references.leftFoot, ref errorMessage) || BipedReferences.LimbError(references.rightThigh, references.rightCalf, references.rightFoot, ref errorMessage) || BipedReferences.LimbError(references.leftUpperArm, references.leftForearm, references.leftHand, ref errorMessage) || BipedReferences.LimbError(references.rightUpperArm, references.rightForearm, references.rightHand, ref errorMessage) || BipedReferences.SpineError(references, ref errorMessage) || BipedReferences.EyesError(references, ref errorMessage);
		}

		// Token: 0x060009A3 RID: 2467 RVA: 0x00034AD8 File Offset: 0x00032ED8
		public static bool SetupWarning(BipedReferences references, ref string warningMessage)
		{
			return BipedReferences.LimbWarning(references.leftThigh, references.leftCalf, references.leftFoot, ref warningMessage) || BipedReferences.LimbWarning(references.rightThigh, references.rightCalf, references.rightFoot, ref warningMessage) || BipedReferences.LimbWarning(references.leftUpperArm, references.leftForearm, references.leftHand, ref warningMessage) || BipedReferences.LimbWarning(references.rightUpperArm, references.rightForearm, references.rightHand, ref warningMessage) || BipedReferences.SpineWarning(references, ref warningMessage) || BipedReferences.EyesWarning(references, ref warningMessage) || BipedReferences.RootHeightWarning(references, ref warningMessage) || BipedReferences.FacingAxisWarning(references, ref warningMessage);
		}

		// Token: 0x060009A4 RID: 2468 RVA: 0x00034B9A File Offset: 0x00032F9A
		private static bool IsNeckBone(Transform bone, Transform leftUpperArm)
		{
			return (!(leftUpperArm.parent != null) || !(leftUpperArm.parent == bone)) && !Hierarchy.IsAncestor(leftUpperArm, bone);
		}

		// Token: 0x060009A5 RID: 2469 RVA: 0x00034BCF File Offset: 0x00032FCF
		private static bool AddBoneToEyes(Transform bone, ref BipedReferences references, BipedReferences.AutoDetectParams autoDetectParams)
		{
			return (!(references.head != null) || Hierarchy.IsAncestor(bone, references.head)) && !(bone.GetComponent<SkinnedMeshRenderer>() != null);
		}

		// Token: 0x060009A6 RID: 2470 RVA: 0x00034C0C File Offset: 0x0003300C
		private static bool AddBoneToSpine(Transform bone, ref BipedReferences references, BipedReferences.AutoDetectParams autoDetectParams)
		{
			if (bone == references.root)
			{
				return false;
			}
			bool flag = bone == references.leftThigh.parent;
			if (flag && !autoDetectParams.legsParentInSpine)
			{
				return false;
			}
			if (references.pelvis != null)
			{
				if (bone == references.pelvis)
				{
					return false;
				}
				if (Hierarchy.IsAncestor(references.pelvis, bone))
				{
					return false;
				}
			}
			return true;
		}

		// Token: 0x060009A7 RID: 2471 RVA: 0x00034C90 File Offset: 0x00033090
		private static void DetectLimb(BipedNaming.BoneType boneType, BipedNaming.BoneSide boneSide, ref Transform firstBone, ref Transform secondBone, ref Transform lastBone, Transform[] transforms)
		{
			Transform[] bonesOfTypeAndSide = BipedNaming.GetBonesOfTypeAndSide(boneType, boneSide, transforms);
			if (bonesOfTypeAndSide.Length < 3)
			{
				return;
			}
			if (bonesOfTypeAndSide.Length == 3)
			{
				firstBone = bonesOfTypeAndSide[0];
				secondBone = bonesOfTypeAndSide[1];
				lastBone = bonesOfTypeAndSide[2];
			}
			if (bonesOfTypeAndSide.Length > 3)
			{
				firstBone = bonesOfTypeAndSide[0];
				secondBone = bonesOfTypeAndSide[2];
				lastBone = bonesOfTypeAndSide[bonesOfTypeAndSide.Length - 1];
			}
		}

		// Token: 0x060009A8 RID: 2472 RVA: 0x00034CE7 File Offset: 0x000330E7
		private static void AddBoneToHierarchy(ref Transform[] bones, Transform transform)
		{
			if (transform == null)
			{
				return;
			}
			Array.Resize<Transform>(ref bones, bones.Length + 1);
			bones[bones.Length - 1] = transform;
		}

		// Token: 0x060009A9 RID: 2473 RVA: 0x00034D0C File Offset: 0x0003310C
		private static bool LimbError(Transform bone1, Transform bone2, Transform bone3, ref string errorMessage)
		{
			if (bone1 == null)
			{
				errorMessage = "Bone 1 of a BipedReferences limb is null.";
				return true;
			}
			if (bone2 == null)
			{
				errorMessage = "Bone 2 of a BipedReferences limb is null.";
				return true;
			}
			if (bone3 == null)
			{
				errorMessage = "Bone 3 of a BipedReferences limb is null.";
				return true;
			}
			Transform transform = (Transform)Hierarchy.ContainsDuplicate(new Transform[]
			{
				bone1,
				bone2,
				bone3
			});
			if (transform != null)
			{
				errorMessage = transform.name + " is represented multiple times in the same BipedReferences limb.";
				return true;
			}
			if (bone2.position == bone1.position)
			{
				errorMessage = "Second bone's position equals first bone's position in the biped's limb.";
				return true;
			}
			if (bone3.position == bone2.position)
			{
				errorMessage = "Third bone's position equals second bone's position in the biped's limb.";
				return true;
			}
			if (!Hierarchy.HierarchyIsValid(new Transform[]
			{
				bone1,
				bone2,
				bone3
			}))
			{
				errorMessage = string.Concat(new string[]
				{
					"BipedReferences limb hierarchy is invalid. Bone transforms in a limb do not belong to the same ancestry. Please make sure the bones are parented to each other. Bones: ",
					bone1.name,
					", ",
					bone2.name,
					", ",
					bone3.name
				});
				return true;
			}
			return false;
		}

		// Token: 0x060009AA RID: 2474 RVA: 0x00034E34 File Offset: 0x00033234
		private static bool LimbWarning(Transform bone1, Transform bone2, Transform bone3, ref string warningMessage)
		{
			Vector3 lhs = Vector3.Cross(bone2.position - bone1.position, bone3.position - bone1.position);
			if (lhs == Vector3.zero)
			{
				warningMessage = string.Concat(new string[]
				{
					"BipedReferences limb is completely stretched out in the initial pose. IK solver can not calculate the default bend plane for the limb. Please make sure you character's limbs are at least slightly bent in the initial pose. First bone: ",
					bone1.name,
					", second bone: ",
					bone2.name,
					"."
				});
				return true;
			}
			return false;
		}

		// Token: 0x060009AB RID: 2475 RVA: 0x00034EB4 File Offset: 0x000332B4
		private static bool SpineError(BipedReferences references, ref string errorMessage)
		{
			if (references.spine.Length == 0)
			{
				return false;
			}
			for (int i = 0; i < references.spine.Length; i++)
			{
				if (references.spine[i] == null)
				{
					errorMessage = "BipedReferences spine bone at index " + i + " is null.";
					return true;
				}
			}
			Transform transform = (Transform)Hierarchy.ContainsDuplicate(references.spine);
			if (transform != null)
			{
				errorMessage = transform.name + " is represented multiple times in BipedReferences spine.";
				return true;
			}
			if (!Hierarchy.HierarchyIsValid(references.spine))
			{
				errorMessage = "BipedReferences spine hierarchy is invalid. Bone transforms in the spine do not belong to the same ancestry. Please make sure the bones are parented to each other.";
				return true;
			}
			for (int j = 0; j < references.spine.Length; j++)
			{
				bool flag = false;
				if (j == 0 && references.spine[j].position == references.pelvis.position)
				{
					flag = true;
				}
				if (j != 0 && references.spine.Length > 1 && references.spine[j].position == references.spine[j - 1].position)
				{
					flag = true;
				}
				if (flag)
				{
					errorMessage = "Biped's spine bone nr " + j + " position is the same as it's parent spine/pelvis bone's position. Please remove this bone from the spine.";
					return true;
				}
			}
			return false;
		}

		// Token: 0x060009AC RID: 2476 RVA: 0x00035000 File Offset: 0x00033400
		private static bool SpineWarning(BipedReferences references, ref string warningMessage)
		{
			return false;
		}

		// Token: 0x060009AD RID: 2477 RVA: 0x00035004 File Offset: 0x00033404
		private static bool EyesError(BipedReferences references, ref string errorMessage)
		{
			if (references.eyes.Length == 0)
			{
				return false;
			}
			for (int i = 0; i < references.eyes.Length; i++)
			{
				if (references.eyes[i] == null)
				{
					errorMessage = "BipedReferences eye bone at index " + i + " is null.";
					return true;
				}
			}
			Transform transform = (Transform)Hierarchy.ContainsDuplicate(references.eyes);
			if (transform != null)
			{
				errorMessage = transform.name + " is represented multiple times in BipedReferences eyes.";
				return true;
			}
			return false;
		}

		// Token: 0x060009AE RID: 2478 RVA: 0x00035097 File Offset: 0x00033497
		private static bool EyesWarning(BipedReferences references, ref string warningMessage)
		{
			return false;
		}

		// Token: 0x060009AF RID: 2479 RVA: 0x0003509C File Offset: 0x0003349C
		private static bool RootHeightWarning(BipedReferences references, ref string warningMessage)
		{
			if (references.head == null)
			{
				return false;
			}
			float verticalOffset = BipedReferences.GetVerticalOffset(references.head.position, references.leftFoot.position, references.root.rotation);
			float verticalOffset2 = BipedReferences.GetVerticalOffset(references.root.position, references.leftFoot.position, references.root.rotation);
			if (verticalOffset2 / verticalOffset > 0.2f)
			{
				warningMessage = "Biped's root Transform's position should be at ground level relative to the character (at the character's feet not at it's pelvis).";
				return true;
			}
			return false;
		}

		// Token: 0x060009B0 RID: 2480 RVA: 0x00035124 File Offset: 0x00033524
		private static bool FacingAxisWarning(BipedReferences references, ref string warningMessage)
		{
			Vector3 vector = references.rightHand.position - references.leftHand.position;
			Vector3 vector2 = references.rightFoot.position - references.leftFoot.position;
			float num = Vector3.Dot(vector.normalized, references.root.right);
			float num2 = Vector3.Dot(vector2.normalized, references.root.right);
			if (num < 0f || num2 < 0f)
			{
				warningMessage = "Biped does not seem to be facing it's forward axis. Please make sure that in the initial pose the character is facing towards the positive Z axis of the Biped root gameobject.";
				return true;
			}
			return false;
		}

		// Token: 0x060009B1 RID: 2481 RVA: 0x000351BC File Offset: 0x000335BC
		private static float GetVerticalOffset(Vector3 p1, Vector3 p2, Quaternion rotation)
		{
			return (Quaternion.Inverse(rotation) * (p1 - p2)).y;
		}

		// Token: 0x04000665 RID: 1637
		public Transform root;

		// Token: 0x04000666 RID: 1638
		public Transform pelvis;

		// Token: 0x04000667 RID: 1639
		public Transform leftThigh;

		// Token: 0x04000668 RID: 1640
		public Transform leftCalf;

		// Token: 0x04000669 RID: 1641
		public Transform leftFoot;

		// Token: 0x0400066A RID: 1642
		public Transform rightThigh;

		// Token: 0x0400066B RID: 1643
		public Transform rightCalf;

		// Token: 0x0400066C RID: 1644
		public Transform rightFoot;

		// Token: 0x0400066D RID: 1645
		public Transform leftUpperArm;

		// Token: 0x0400066E RID: 1646
		public Transform leftForearm;

		// Token: 0x0400066F RID: 1647
		public Transform leftHand;

		// Token: 0x04000670 RID: 1648
		public Transform rightUpperArm;

		// Token: 0x04000671 RID: 1649
		public Transform rightForearm;

		// Token: 0x04000672 RID: 1650
		public Transform rightHand;

		// Token: 0x04000673 RID: 1651
		public Transform head;

		// Token: 0x04000674 RID: 1652
		public Transform[] spine = new Transform[0];

		// Token: 0x04000675 RID: 1653
		public Transform[] eyes = new Transform[0];

		// Token: 0x020001D4 RID: 468
		public struct AutoDetectParams
		{
			// Token: 0x060009B2 RID: 2482 RVA: 0x000351E3 File Offset: 0x000335E3
			public AutoDetectParams(bool legsParentInSpine, bool includeEyes)
			{
				this.legsParentInSpine = legsParentInSpine;
				this.includeEyes = includeEyes;
			}

			// Token: 0x170000C7 RID: 199
			// (get) Token: 0x060009B3 RID: 2483 RVA: 0x000351F3 File Offset: 0x000335F3
			public static BipedReferences.AutoDetectParams Default
			{
				get
				{
					return new BipedReferences.AutoDetectParams(true, true);
				}
			}

			// Token: 0x04000676 RID: 1654
			public bool legsParentInSpine;

			// Token: 0x04000677 RID: 1655
			public bool includeEyes;
		}
	}
}
